#include "soc_gpio.h"
#include "main.h"


#define GPIO_ASSERT_EN 0  //因为GPIO调用概率高，这里做优化

#define ToSocPort(port) (GPIO_TypeDef*)(m_ports[(int)port])
#define ToSocPin(pin) (0x0001U << pin)
#define ToSocPinState(val) ((GPIO_PinState)val) //(val == 1? GPIO_PinState::GPIO_PIN_SET:GPIO_PinState::GPIO_PIN_RESET)

const static GPIO_TypeDef* m_ports[] = {
#ifdef GPIOA
    GPIOA,
#else 
    nullptr,
#endif 

#ifdef GPIOB
    GPIOB,
#else 
    nullptr,
#endif 

#ifdef GPIOC
    GPIOC,
#else 
    nullptr,
#endif 

#ifdef GPIOD
    GPIOD,
#else 
    nullptr,
#endif 

#ifdef GPIOE
    GPIOE,
#else 
    nullptr,
#endif 

#ifdef GPIOF
    GPIOF,
#else 
    nullptr,
#endif 

#ifdef GPIOG
    GPIOG,
#else 
    nullptr,
#endif 

#ifdef GPIOH
    GPIOH,
#else 
    nullptr,
#endif 

#ifdef GPIOI
    GPIOI,
#else 
    nullptr,
#endif 
};

static void inline __WriteImpl(GpioPort port, uint8_t pin, int val)
{
#if GPIO_ASSERT_EN > 0
    ASSERT_ARRAY_INDEX_0(m_ports, port);
#endif 

    HAL_GPIO_WritePin(ToSocPort(port), ToSocPin(pin), ToSocPinState(val));
}

static void inline __ToggleImpl(GpioPort port, uint8_t pin)
{
#if GPIO_ASSERT_EN > 0
    ASSERT_ARRAY_INDEX_0(m_ports, port);
#endif 
    
    HAL_GPIO_TogglePin(ToSocPort(port), ToSocPin(pin));
}

static int inline __ReadImpl(GpioPort port, uint8_t pin)
{
#if GPIO_ASSERT_EN > 0
    ASSERT_ARRAY_INDEX_0(m_ports, port);
#endif 

    return HAL_GPIO_ReadPin(ToSocPort(port), ToSocPin(pin));
}

SOC_Gpio::SOC_Gpio()
{

}

SOC_Gpio::SOC_Gpio(GpioPort port, uint8_t pin)
{
    m_port = port;
    m_pin = pin;
}

SOC_Gpio::SOC_Gpio(const GpioPortPin &portPin)
{
    m_port = portPin.Port;
    m_pin = portPin.Pin;
}

SOC_Gpio::~SOC_Gpio()
{
}

void SOC_Gpio::Toggle()
{
    __ToggleImpl(m_port, m_pin);
}

void SOC_Gpio::Write(int val)
{
    __WriteImpl(m_port, m_pin, val);
}

void SOC_Gpio::Set()
{
    __WriteImpl(m_port, m_pin, 1);
}

void SOC_Gpio::Clear()
{
    __WriteImpl(m_port, m_pin, 0);
}

int SOC_Gpio::Read()
{
    return __ReadImpl(m_port, m_pin);
}

void SOC_Gpio::Toggle(GpioPort port, uint8_t pin)
{
    __ToggleImpl(port, pin);
}

void SOC_Gpio::Write(GpioPort port, uint8_t pin, int val)
{
    __WriteImpl(port, pin, val);
}

void SOC_Gpio::Set(GpioPort port, uint8_t pin)
{
    __WriteImpl(port, pin, 1);
}

void SOC_Gpio::Clear(GpioPort port, uint8_t pin)
{
    __WriteImpl(port, pin, 0);
}

int SOC_Gpio::Read(GpioPort port, uint8_t pin)
{
    return __ReadImpl(port, pin);
}

void SOC_Gpio::Toggle(const GpioPortPin &portPin)
{
    __ToggleImpl(portPin.Port, portPin.Pin);
}

void SOC_Gpio::Write(const GpioPortPin &portPin, int val)
{
    __WriteImpl(portPin.Port, portPin.Pin, val);
}

void SOC_Gpio::Set(const GpioPortPin &portPin)
{
    __WriteImpl(portPin.Port, portPin.Pin, 1);
}

void SOC_Gpio::Clear(const GpioPortPin &portPin)
{
    __WriteImpl(portPin.Port, portPin.Pin, 0);
}

int SOC_Gpio::Read(const GpioPortPin &portPin)
{
    return __ReadImpl(portPin.Port, portPin.Pin);
}
